############# ########### ####### ##### ### ##
#
# Copyright (C) 2010 The Hursk Group, LLC
#
# This program is free software: you can redistribute it and/or modify 
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (See file named COPYING).  If not, see 
# <http://www.gnu.org/licenses/>.
# 
############# ########### ####### ##### ### ##

#!/usr/bin/perl -w
use strict;
use Cwd;
# Directory of the extracted .tbz2 files and this script:
my $cwd = cwd();
use LWP::Simple;
use Time::localtime;

our $USAGE = <<HEREDOC

USAGE:

**********************************************************************************
`perl place_in_dir_above_host_dirs_along_with_all_accompanying_files.pl
    [nkf arguments, i.e. `-w8` for SHIFT-JIS]
    [--no_patches_newer_than=yyyymmdd]
    <other arguments>`
**********************************************************************************

The following arguments are required:
* nkf arguments are required! If no nkf decoding is necessary, use the argument --NONE
* --no_patches_newer_than=yyyymmdd      You may enter "today" (without the quotes) instead of yyyymmdd.

If you'd like to skip the downloading of the patchdiag.xref file, use the argument --SKIP_XREF_DOWNLOAD

Run `nkf --help` for more nkf options

HEREDOC
;

STATUS(500, $USAGE) if not grep {/\w/} @ARGV;

my $nkf_is_installed = `which nkf`;
STATUS(500, "Please install nkf through your package management system")
    if (not $nkf_is_installed or $nkf_is_installed =~ /^\s*$/);

unless (exists($ARGV[0])){warn $USAGE; exit}
my @nkf_args;
ARGS:
for (@ARGV){
    chomp;
    if ($_ =~ /^\-*(h|help)$/){warn $USAGE; exit}
    elsif (/no_patches_newer_than
	   |NONE
	   |SKIP_XREF_DOWNLOAD/ix
	){
	next ARGS;
    }
    else {push @nkf_args, $_}
}

my $no_patches_newer_than = (grep {/no_patches_newer_than/} @ARGV)[0];
if (not $no_patches_newer_than or $no_patches_newer_than =~ /^\s*$/){
    STATUS(500, "The --no_patches_newer_than was missing. "
	    ."See the proper format in the usage below:\n $USAGE");
}
$no_patches_newer_than = _no_patches_newer_than( $no_patches_newer_than );

sub _no_patches_newer_than {
    my $dash_dash_no_patches_newer_than_equals_yyyymmdd = shift;
    my $yyyymmdd = $dash_dash_no_patches_newer_than_equals_yyyymmdd;
    if ($yyyymmdd =~ /today/i){
	my $return_val = localtime->year() + 1900;
	$return_val = "$return_val". localtime->mon() + 1;
	$return_val = "$return_val". localtime->mday();
	return "$return_val";#Ensure string instead of number
    }
    #sec, min, hour, mday, mon, year, wday, yday, and isdst.
    my $curr_year = localtime->year() + 1900;
    my $first_digit_curr_year = ($curr_year =~ m/^(\d)/)[0];
    my $second_digit_curr_year = ($curr_year =~ m/^\d(\d)/)[0];
    my $third_digit_curr_year = ($curr_year =~ m/^\d{2}(\d)/)[0];
    my $fourth_digit_curr_year = ($curr_year =~ m/^\d{3}(\d)/)[0];
    
    my $curr_month = localtime->mon() + 1;
    my $first_digit_curr_month = ($curr_month =~ m/^(\d)/)[0];
    my $second_digit_curr_month = ($curr_month =~ m/^\d(\d)/)[0];
    
    my $curr_day = localtime->mday();
    my $first_digit_curr_day = ($curr_day =~ m/^(\d)/)[0];
    my $second_digit_curr_day = ($curr_day =~ m/^\d(\d)/)[0];
    
    if ($yyyymmdd =~ /-+no_patches_newer_than=
	(
	    [1-$first_digit_curr_year] 
	    [0-$second_digit_curr_year]
	    [0-$third_digit_curr_year]
	    [0-$fourth_digit_curr_year]
	    [0-1]
	    [0-9]
	    [0-3]
	    [0-9]
	)
	\s*
	$
    /x){
	$yyyymmdd = $1;
	if ("$yyyymmdd" ne "$curr_year$curr_month$curr_day"){
	    warn "WARNING: You did not enter today's date for the no_patches_newer_than argument!\n"
	    ."You entered $yyyymmdd as the date for the no_patches_newer_than argument";
	    sleep 3;
	}
    }
    else {
	STATUS(500, "The --no_patches_newer_than was not properly formatted. "
	    ."See the proper format in the usage below:\n $USAGE");
    }
    return $yyyymmdd;
}

my $scratchdir = "$cwd/scratch";
mkdir $scratchdir unless -d $scratchdir;

# Output pkginfo file 
my $pkgoutputfile = "$scratchdir/pkginfo.out";
#`touch $pkgoutputfile`; `rm scratch/$pkgoutputfile`;

# Output file 
my $outputfile = "$scratchdir/patchdiag.csv";
unlink $outputfile if -f $outputfile;
#`touch $outputfile`; `rm scratch/$outputfile`;

#Get new/updated patchdiag.xref file:
# Location of the patchdiag.xref file:
my $patchdiag_xref_file = "$cwd/patchdiag.xref";
unless (grep {/SKIP_XREF_DOWNLOAD/i} @ARGV){
    print STDERR "Downloading patchdiag.xref file from Sun...";
    
    my $patchdiag_xref_url = 'http://sunsolve.sun.com/pdownload.do?target=patchdiag.xref';
    my $patchdiag_xref_text = LWP::Simple::get( $patchdiag_xref_url );
    
    STATUS(500, "The patchdiag.xref file was blank when retrieved from $patchdiag_xref_url")
	if (not $patchdiag_xref_text or $patchdiag_xref_text =~ /^\s*$/);
    open FH, ">", $patchdiag_xref_file;
    print FH $patchdiag_xref_text;
    close FH;
}
else {
    print STDERR "Skipping xref file download";
}

STATUS(500, "File \"$patchdiag_xref_file\" does not exist") unless -e $patchdiag_xref_file;

# Location of the sed file that substitutes ip to host
my $iphostsed = "$cwd/host_ip.sed";
STATUS(500, "File \"$iphostsed\" does not exist") unless -e $iphostsed;

# Location of the pkginfo awk script
my $pkginfo_perl = "$cwd/pkginfo_parser.pl";
STATUS(500, "File \"$pkginfo_perl\" does not exist") unless -e $pkginfo_perl;

# Location of the awk script that does the magic
my $patchdiag_perl = "$cwd/patchdiag.pl";
STATUS(500, "File \"$patchdiag_perl\" does not exist") unless -e $patchdiag_perl;

# Location of the sed file that substitutes ip to host
#setenv iphostsed "/path/to/host_ip.sed"
#[ -e "$iphostsed" ] || echo "File "$iphostsed" does not exist" && exit 1 

# First run the pkginfo script to get out input in a good format
HOST_DIRS:
foreach my $dir ( `ls -d */ ` ) {
    chomp $dir;
    next HOST_DIRS if $dir =~ /scratch\s*$/;
    
    if ($dir =~ /\/$/){#Take off end "/" on dir path
	    local ($_);
	    $_=$dir; s/\/$//; $dir = $_;
    }
    my $pkg_info_file = "$dir/pkginfo.long.out";
    
    unless (-f $pkg_info_file){
	print STDERR "No pkginfo.long.out in $dir\n";
	next HOST_DIRS;
    }
    
    unless (grep {/none/i} @ARGV){
	
	push my @cmd, ('nkf ', @nkf_args, $pkg_info_file);
	my $cmd = "@cmd";
	my $output = `$cmd`;
	my $tempfile = $pkg_info_file.'.'."$$".'.'.'temp';# "$$" means current PID.
	`cp $pkg_info_file $tempfile`;
	unlink $pkg_info_file or STATUS(500, "Could not unlink pkg_info_file $pkg_info_file");
	open FH, ">", $pkg_info_file or STATUS(500, "Could not open $pkg_info_file for writing");
	print FH $output;
	close FH or STATUS(500, "Could not close filehandle for $pkg_info_file");
	unlink $tempfile or STATUS(500, "Could not unlink tempfile $tempfile");
	undef @cmd;
    }
    #`awk -f "$pkginfoawk" $pkg_info_file > "$pkgoutputfile" 2> $stderr`;
    require 'pkginfo_parser.pl';#package 'pkginfo_parser'
    my $pkginfo_output = pkginfo_parser::process( $pkg_info_file, $dir );
    
    #Print pkginfo_output to the pkgoutputfile file:
    open FH, ">", $pkgoutputfile;
    print FH $pkginfo_output;
    close FH;
    
    #`awk -v ip=$dir -f "$patchdiagawk" pass=1 $dir/showrevp.out pass=2 "$pkgoutputfile" pass=3 $dir/uname.out pass=4 "$patchdiag"  >> "$outputfile"`;
    require 'patchdiag.pl';#package 'patchdiag'
    my %args = (
	ip => $dir,
	pass1 => "$dir/showrevp.out",
	pass2 => $pkgoutputfile,
	pass3 => "$dir/uname.out",
	pass4 => $patchdiag_xref_file,
	nonewerthan => $no_patches_newer_than,
    );
    my $patchdiag_output = patchdiag::process( \%args );
    
    open FH, ">>", $outputfile;
    print FH $patchdiag_output;
    close FH;
}

`sed -i "" -f "$iphostsed" "$outputfile"`;

sub STATUS {
	my $number = shift;
	my $errstr = shift;
	$errstr = "\n" . "-" x 75 . "\n" . $errstr;
	die $errstr;
}
